﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Text;
using System.IO.IsolatedStorage;
using System.IO;
using System.Xml.Linq;
using System.Linq;

namespace SmartHYU_TestVersion.Life
{
    
    public class HYUbob
    {
        /* **************************************
         *      Public member properties        *
         ****************************************/
        public class BobInfo
        {

            // Date info
            public string Year { get; set; }
            public string Month { get; set; }
            public string Day { get; set; }

            // Place
            public string Campus { get; set; }
            public string Place { get; set; }
            public string Comment { get; set; }

            // Type & Operation
            public string Time { get; set; }
            public string IsClosed { get; set; }
            public string WhyClosed { get; set; }

            // menu info
            public string Name { get; set; }
            public string Price { get; set; }
            public string Description { get; set; }

        }

        // Menu List
        public List<BobInfo> BobInfos = new List<BobInfo>();

        // Others
        public string DebugText { get; set; }

        /****************************************
         *      Private member properties       *
         ****************************************/
        protected string bobFilePath = "bob.rss";
        protected string bobXML { get; set; }


        /* **************************************************************************
         *      Constructor                                                         *
         ****************************************************************************/
        public HYUbob()
        {
            // nothing to do
        }

        /* **************************************************************************
         *      Methods                                                             *
         ****************************************************************************/

        /*
        // Default Argument
        public bool downloadMenuAsync()
        {
            return downloadMenuAsync("icewall", "Seoul");
        }

        public bool downloadMenuAsync(string appID)
        {
            return downloadMenuAsync(appID, "Seoul");
        }
         */

        // download menu with API and save it to IsolatedStorage 
        public bool DownloadMenuAsync(string appID, string campus = "Seoul")
        {
            // validate input
            if (campus != "Seoul" && campus != "Erica")
            {
                System.Diagnostics.Debug.WriteLine("Invalid campus code");
                MessageBox.Show("Error: Invalid campus code");

                return false;
            }

            // construct Uri string
            StringBuilder urlToLoad = new StringBuilder("http://icewall.hanyang.ac.kr/hyum/request_menu.php?id=");
            urlToLoad.Append(appID);
            urlToLoad.Append("&campus=");
            urlToLoad.Append(campus);

            // Download
            WebClient menuLoader = new WebClient();
            menuLoader.DownloadStringAsync(new Uri(urlToLoad.ToString()));
            menuLoader.DownloadStringCompleted += new DownloadStringCompletedEventHandler(menuLoader_DownloadStringCompleted);

            return true;
        }

        void menuLoader_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            // check connection
            if (e.Error != null)
            {
                OnDownloadBobCompleted();
                return;
            }

            string rawBobXML;
            string bobFilePath = this.bobFilePath;

            this.DebugText = e.Result;
            rawBobXML = e.Result;

            // File open and save
            using (IsolatedStorageFile rssStorage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                IsolatedStorageFileStream rssStream = new IsolatedStorageFileStream(bobFilePath, FileMode.OpenOrCreate, rssStorage);
                StreamWriter rssWriter = new StreamWriter(rssStream);

                // Try to Save XML
                try
                {
                    rssWriter.Write(rawBobXML);
                }

                catch (IsolatedStorageException fileWriteExpection)
                {
                    // Exception Handling : Message Box
                    StringBuilder errorMessage = new StringBuilder("File Write Error (RSS Content) : ");
                    errorMessage.Append(fileWriteExpection.Message);
                    MessageBox.Show(errorMessage.ToString());
                }

                // Close Streams
                rssWriter.Close();
                rssStream.Close();
            }
            // END : File open and save


            // Generate Event to notify download and save was completed
            OnDownloadBobCompleted();
        }

        // -----------------------------------------------------------------------------------------

        // Load XML from Isolated Storage 
        //          Loaded XML will be stored in this.bobXML
        private bool loadXmlFromIsolatedStorage()
        {
            // File open and read
            using (IsolatedStorageFile bobFile = IsolatedStorageFile.GetUserStoreForApplication())
            {
                // checks if file exists
                if (!bobFile.FileExists(this.bobFilePath))
                {
                    return false;
                }

                IsolatedStorageFileStream bobStream = new IsolatedStorageFileStream(this.bobFilePath, FileMode.Open, bobFile);
                StreamReader bobReader = new StreamReader(bobStream);

                // Try to read
                try
                {
                    this.bobXML = bobReader.ReadToEnd().ToString();
                }

                // Exception Handling
                catch (IsolatedStorageException isolatedException)
                {
                    MessageBox.Show("XML File Read Error " + isolatedException.Message);
                    return false;
                }

                bobReader.Close();
                bobStream.Close();
            }
            // END : File open and read

            this.DebugText = this.bobXML;
            return true;
        }

        // -----------------------------------------------------------------------------------------


        public bool ParseXmlFromIsolatedStorage()
        {
            if (!this.loadXmlFromIsolatedStorage())
            {
                MessageBox.Show("Failed to read Bob data from storage");
                return false;
            }

            // XML Parser
            XDocument bobParser = XDocument.Parse(this.bobXML);


            // LINQ to XML
            var bobLinqResult = from bobLinq in bobParser.Descendants("date")
                                select new
                                {
                                    Year = bobLinq.Attribute("year").Value,
                                    Month = bobLinq.Attribute("month").Value,
                                    Day = bobLinq.Attribute("day").Value,

                                    ArrayByPlace = from bobLinqByPlace in bobLinq.Descendants("place")
                                                   select new
                                                   {
                                                       Place = bobLinqByPlace.Attribute("name").Value,
                                                       Campus = bobLinqByPlace.Attribute("campus").Value,
                                                       Comment = bobLinqByPlace.Element("comment").Value,

                                                       ArrayByTime = from bobLinqByTime in bobLinqByPlace.Descendants("time")
                                                                     select new
                                                                     {
                                                                         Type = bobLinqByTime.Attribute("type").Value,
                                                                         IsClosed = bobLinqByTime.Element("isClosed").Attribute("value").Value,
                                                                         WhyClosed = bobLinqByTime.Element("isClosed").Value,

                                                                         arrayByMenu = from bobLinqByMenu in bobLinqByTime.Descendants("menu")
                                                                                       select new
                                                                                       {
                                                                                           Name = bobLinqByMenu.Element("name").Value,
                                                                                           Price = bobLinqByMenu.Element("price").Value,
                                                                                           Description = bobLinqByMenu.Element("desc").Value
                                                                                       }
                                                                     }

                                                   }
                                };
            // END : LINQ to XML

            // ------------------------------------------------

            // Extract to BobInfos List
            foreach (var menuElement in bobLinqResult)
            {
                foreach (var menuElementByPlace in menuElement.ArrayByPlace)
                {
                    foreach (var menuElementByTime in menuElementByPlace.ArrayByTime)
                    {
                        foreach (var menuElementByMenu in menuElementByTime.arrayByMenu)
                        {
                            BobInfo bobInfo = new BobInfo();

                            bobInfo.Year = menuElement.Year;
                            bobInfo.Month = menuElement.Month;
                            bobInfo.Day = menuElement.Day;

                            bobInfo.Place = menuElementByPlace.Place;
                            bobInfo.Campus = menuElementByPlace.Campus;
                            bobInfo.Comment = menuElementByPlace.Comment;

                            bobInfo.Time = menuElementByTime.Type;
                            bobInfo.IsClosed = menuElementByTime.IsClosed;
                            bobInfo.WhyClosed = menuElementByTime.WhyClosed;

                            bobInfo.Name = menuElementByMenu.Name;
                            bobInfo.Price = menuElementByMenu.Price;
                            bobInfo.Description = menuElementByMenu.Description;

                            this.BobInfos.Add(bobInfo);
                        }
                    }
                }
            }

            return true;
        }

        // -----------------------------------------------------------------------------------------

        public List<string> GetRestaurantListFromDay(int dayToSearch)
        {

            // dummy code
            List<string> dummyList = new List<string>();
            dummyList.Add("");
            // END

            List<string> restaurantList = new List<string>();

            // Search... 
            foreach (var restaurant in this.BobInfos)
            {
                if ((restaurant.Day == dayToSearch.ToString()) && (!restaurantList.Contains(restaurant.Place)))
                {
                    restaurantList.Add(restaurant.Place);
                }
            }

            return restaurantList;
        }

        // -----------------------------------------------------------------------------------------

        // dummy method for test - will be deleted before release
        public List<string> GetDateList()
        {

            // Load data from storage
            if (!this.loadXmlFromIsolatedStorage())
            {
                MessageBox.Show("Failed to read Bob data from storage");
                return new List<string>();
            }

            // List
            List<string> dateList = new List<string>();

            // Parsing ...
            XDocument bobParserForDate = XDocument.Parse(this.bobXML);

            var bobLinqForDateResult = from bobLinq in bobParserForDate.Descendants("date")
                                       select new
                                       {
                                           Year = bobLinq.Attribute("year").Value,
                                           Month = bobLinq.Attribute("month").Value,
                                           Day = bobLinq.Attribute("day").Value
                                       };

            // Make into string - YYYY/MM/DD
            string dateFormatString;
            foreach (var dateProperties in bobLinqForDateResult)
            {
                StringBuilder dateFormatBuilder = new StringBuilder();
                dateFormatBuilder.Append(dateProperties.Year);
                dateFormatBuilder.Append("/");
                dateFormatBuilder.Append(dateProperties.Month);
                dateFormatBuilder.Append("/");
                dateFormatBuilder.Append(dateProperties.Day);

                dateFormatString = dateFormatBuilder.ToString();

                dateList.Add(dateFormatString);
            }


            return dateList;
        }

        // -----------------------------------------------------------------------------------------

        public List<BobDate> GetDateListToBobDate()
        {

            // Load data from storage
            if (!this.loadXmlFromIsolatedStorage())
            {
                MessageBox.Show("Failed to read Bob data from storage");
                return new List<BobDate>();
            }

            List<BobDate> myBobDates = new List<BobDate>();

            // Parsing ...
            XDocument bobParserForDate = XDocument.Parse(this.bobXML);

            var bobLinqForDateResult = from bobLinq in bobParserForDate.Descendants("date")
                                       select new
                                       {
                                           Year = bobLinq.Attribute("year").Value,
                                           Month = bobLinq.Attribute("month").Value,
                                           Day = bobLinq.Attribute("day").Value
                                       };

            // Make into string - YYYY/MM/DD
            //      and make BobDate List
            string dateFormatString;

            foreach (var dateProperties in bobLinqForDateResult)
            {
                BobDate myBobDate = new BobDate();
                StringBuilder dateFormatBuilder = new StringBuilder();
                dateFormatBuilder.Append(dateProperties.Year);
                dateFormatBuilder.Append("/");
                dateFormatBuilder.Append(dateProperties.Month);
                dateFormatBuilder.Append("/");
                dateFormatBuilder.Append(dateProperties.Day);

                dateFormatString = dateFormatBuilder.ToString();

                // Set single instance
                myBobDate.DateByString = dateFormatString;
                myBobDate.DateByInteger = int.Parse(dateProperties.Day);

                // Add to List
                myBobDates.Add(myBobDate);


                // dateList.Add(dateFormatString);
            }

            // dummy return
            return myBobDates;
        }

        // -----------------------------------------------------------------------------------------

        public List<SimpleBobInfo>
            GetSimpleBobInfoListFromDayAndRestaurant(
                                        int dayToSearch,
                                        string restaurantToSearch)
        {
            List<SimpleBobInfo> mySimpleBobInfos = new List<SimpleBobInfo>();

            foreach (var simpleBobInfo in this.BobInfos)
            {

                if ((simpleBobInfo.Day == dayToSearch.ToString()) && (simpleBobInfo.Place == restaurantToSearch))
                {
                    SimpleBobInfo mySimpleBobInfo = new SimpleBobInfo();

                    // insert data - kind of SabJil
                    mySimpleBobInfo.Campus = simpleBobInfo.Campus;
                    mySimpleBobInfo.Place = simpleBobInfo.Place;
                    mySimpleBobInfo.Comment = simpleBobInfo.Comment;
                    mySimpleBobInfo.Time = simpleBobInfo.Time;
                    mySimpleBobInfo.IsClosed = simpleBobInfo.IsClosed;
                    mySimpleBobInfo.WhyClosed = simpleBobInfo.WhyClosed;
                    mySimpleBobInfo.Name = simpleBobInfo.Name;
                    mySimpleBobInfo.Price = simpleBobInfo.Price;
                    mySimpleBobInfo.Description = simpleBobInfo.Description;

                    mySimpleBobInfos.Add(mySimpleBobInfo);
                }


            }

            return mySimpleBobInfos;
            //return new List<SimpleBobInfo>();
        }

        // -----------------------------------------------------------------------------------------

        public List<SimpleBobInfo> GetSimpleBobInfoListFromDay(int dayToSearch)
        {
            List<SimpleBobInfo> mySimpleBobInfos = new List<SimpleBobInfo>();

            foreach (var simpleBobInfo in this.BobInfos)
            {
                if (simpleBobInfo.Day == dayToSearch.ToString() )
                {
                    SimpleBobInfo mySimpleBobInfo = new SimpleBobInfo();

                    // insert data - kind of SabJil
                    mySimpleBobInfo.Campus = simpleBobInfo.Campus;
                    mySimpleBobInfo.Place = simpleBobInfo.Place;
                    mySimpleBobInfo.Comment = simpleBobInfo.Comment;
                    mySimpleBobInfo.Time = simpleBobInfo.Time;
                    mySimpleBobInfo.IsClosed = simpleBobInfo.IsClosed;
                    mySimpleBobInfo.WhyClosed = simpleBobInfo.WhyClosed;
                    mySimpleBobInfo.Name = simpleBobInfo.Name;
                    mySimpleBobInfo.Price = simpleBobInfo.Price;
                    mySimpleBobInfo.Description = simpleBobInfo.Description;

                    mySimpleBobInfos.Add(mySimpleBobInfo);
                }
            }
            return mySimpleBobInfos;
        }

        /********************************************************************************
         *      User Defined Event                                                      *
         ********************************************************************************/
        public delegate void DownloadBobComplete(bool completedStatus, string bobMenu);
        public event DownloadBobComplete downloadBobCompleted;
        protected void OnDownloadBobCompleted() { downloadBobCompleted(true, this.DebugText); }

        public delegate void LoadBobStatus(bool completedStatus, string bobMenu);
        public event LoadBobStatus loadBobCompleted;
        protected void OnLoadBobCompleted() { loadBobCompleted(true, this.DebugText); }

    }

    // BobDate class : ( YYYY/MM/DD, DD )
    public class BobDate
    {
        public string DateByString { get; set; }
        public int DateByInteger { get; set; }
    }

    // SimpleBobInfo class 
    public class SimpleBobInfo
    {
        // General info
        public string Campus { get; set; }
        public string Place { get; set; }
        public string Comment { get; set; }

        // Type & Operation
        public string Time { get; set; }
        public string IsClosed { get; set; }
        public string WhyClosed { get; set; }

        // menu info
        public string Name { get; set; }
        public string Price { get; set; }
        public string Description { get; set; }
    }
}
